package com.witsoft.device.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.witsoft.device.dao.DeviceDao;
import com.witsoft.device.entity.DeviceEntity;
import com.witsoft.device.enums.Status;
import com.witsoft.device.model.DeviceQuota;
import com.witsoft.device.model.DeviceQuotaListInfo;
import com.witsoft.device.model.DeviceTotalInfo;
import com.witsoft.device.model.bo.DeviceQuotaBO;
import com.witsoft.device.service.DeviceDayReporterService;
import com.witsoft.device.service.DeviceService;
import com.witsoft.device.service.DeviceStatusTimeLineService;
import com.witsoft.device.utils.DateUtil;
import com.witsoft.device.utils.Result;
import com.witsoft.manager.FeignManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;

@Slf4j
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceDao, DeviceEntity> implements DeviceService{

    @Resource
    private DeviceDao deviceDao;

    @Resource
    private DeviceStatusTimeLineService deviceStatusTimeLineService;

    //性能开动率 标准节拍(配置参数值，可由mes传过来)/（运行时间/生产产量）*100%
    @Value("${gongli.device.setPerformance}")
    private Integer setPerformance;

    @Autowired
    private FeignManager feignManager;

    @Resource
    private DeviceDayReporterService dayReporterService;



    @Override
    public Map getBeatMultiplyWorkReportOfYear(String deviceCodes) {

        Map beatMultiplyWorkReportOfYear = feignManager.getBeatMultiplyWorkReportOfYear(deviceCodes);
        return beatMultiplyWorkReportOfYear;
    }


    @Override
    public Map<String, Double> getBeatMultiplyWorkReportOfDay(String deviceCodes, Date start, Date end, String type) {

        return feignManager.getBeatMultiplyWorkReportOfDay(deviceCodes, start, end, type);
    }


    @Override
    public DeviceQuotaListInfo getAverageDeviceTarget() {

        DeviceQuotaListInfo totalDeviceQuota = new DeviceQuotaListInfo();
        List<DeviceQuota> datas = new ArrayList<>();

        try{
            DecimalFormat df = new DecimalFormat("#");
            List<DeviceEntity> list = this.getAllList();

            if(!CollectionUtils.isEmpty(list)){

                double sumQuantity = 0, sumPerformance = 0, sumAvailability = 0, sumOee  = 0;
                Double quantityRate = 0d, performanceRate = 0.0, availability = 0.0;

                //TODO 获取mes的所有设备的节拍数和有效产品数的乘积
                String deviceCodes = getDeviceCodes(list);
                Date start = DateUtil.getCurrentZero(new Date());   //获取当天零点零分零秒的日期
                Map<String, Double> workReport = getBeatMultiplyWorkReportOfDay(deviceCodes, start, new Date(), "day");
                //获取所有设备的不合格数
                Map<String, String> badCountMap = feignManager.getBadProductCountByDevice(deviceCodes);

                for(DeviceEntity deviceEntity : list){
                    DeviceQuota deviceQuota = new DeviceQuota();
                    Long sumCount = deviceEntity.getTotalCount();
                    //今日不合格数
                    Long badCount = 0l;


                    //feature(2022.01.13):
                    //计算今日生产总数， -->设备表存的是设备当年总的生产数
                    Long lastDayProductTotal = dayReporterService.getLastDayProductTotal(deviceEntity.getId());
                    if(!ObjectUtils.isEmpty(lastDayProductTotal) && lastDayProductTotal < sumCount){
                        //今日生产总数
                        sumCount = sumCount - lastDayProductTotal;
                    }

                    //合格率计算： 合格数量/总数量
                    deviceQuota.setQuantity("0");
                    if(!ObjectUtils.isEmpty(sumCount) && sumCount > 0){

                        String badNumber = badCountMap.get(deviceEntity.getName());
                        if(!ObjectUtils.isEmpty(badNumber)){
                            badCount = Long.parseLong(badNumber);
                        }

                        quantityRate = 1.0 * (sumCount - badCount) / sumCount;
                        deviceQuota.setQuantity(df.format(quantityRate * 100));
                    }


                    //性能开动率计算：
                    //取当前设备当天的所有运行时长(单位：秒)
                    //fixed（2021.11.15）：通过mes获取设备的节拍和报工数量的乘积
                    Double reportNum = workReport.get(deviceEntity.getName());
                    if(ObjectUtils.isEmpty(reportNum)){
                        reportNum = 0.0;
                    }

                    //fixed(2022.02.21): mes获取透传的节拍和报工数乘积，mes改成以分钟为单位，这里需要适配一下
                    reportNum = reportNum * 60;

                    int sumRunning = deviceStatusTimeLineService.getSumRunningTimeDay(deviceEntity.getId());
                    if(sumRunning > 0){
                        //v2:
                        performanceRate = 1.0 * reportNum / sumRunning;
                        //v1:
                        //performanceRate = (1.0 * deviceMeter) / (1.0 * sumRunning/deviceEntity.getTotalCount());
                    }
                    deviceQuota.setPerformance(df.format(performanceRate * 100));


                    //时间开动率计算：
                    //取当前设备当天的所有记录时长(单位：秒)
                    int sumTime = deviceStatusTimeLineService.getSumTime(deviceEntity.getId());
                    //fixed(2022.04.07): 获取实时开机时长,与历史开机时长相加    2022.04.07
                    Long realOpeningTimeCurrentDay = deviceStatusTimeLineService.getRealOpeningTimeCurrentDay(deviceEntity.getId());
                    sumTime = sumTime + realOpeningTimeCurrentDay.intValue();
                    log.info("当前设备的实时总开机时间：{}", sumTime);

                    availability = sumTime <= 0 ? 0 : (1.0 * sumRunning) / sumTime;
                    deviceQuota.setAvailability(df.format(availability * 100));


                    //oee计算：
                    Double oeeRate = quantityRate * performanceRate * availability;
                    deviceQuota.setOee(df.format(oeeRate * 100));


                    //所有设备指标累计计算：
                    sumQuantity += quantityRate;
                    sumPerformance += performanceRate;
                    sumAvailability += availability;
                    sumOee += oeeRate;

                    deviceQuota.setDeviceName(deviceEntity.getName());
                    deviceQuota.setSerialNumber(deviceEntity.getSerialNumber());
                    datas.add(deviceQuota);
                }

                totalDeviceQuota.setAllQuantity(sumQuantity <= 0 ? "0" : df.format((sumQuantity/list.size())*100));
                totalDeviceQuota.setAllPerformance(sumPerformance <= 0 ? "0" : df.format((sumPerformance/list.size())*100));
                totalDeviceQuota.setAllAvailability(sumAvailability<= 0 ? "0" : df.format((sumAvailability/list.size())*100));
                totalDeviceQuota.setAllOee(sumOee <= 0 ? "0" : df.format((sumOee/list.size())*100));

                totalDeviceQuota.setList(datas);
            }
        }catch (Exception e){
            log.error("获取设备平均指标异常：{}", e.getMessage());
            return null;
        }

        return totalDeviceQuota;
    }


    private String getDeviceCodes(List<DeviceEntity> list){

        StringBuffer codes = new StringBuffer();
        list.forEach(deviceEntity -> {
            codes.append(deviceEntity.getName()).append(",");
        });

        String deviceCodes = codes.substring(0, codes.length() - 1);
        return deviceCodes;
    }


    @Override
    public DeviceQuotaBO getAverageDeviceTargetByDeviceId(String deviceId) {

        DeviceEntity deviceEntity = getInfo(deviceId);
        if(ObjectUtils.isEmpty(deviceEntity)){
            return null;
        }

        //DecimalFormat df = new DecimalFormat("#");
        DeviceQuotaBO deviceQuota = new DeviceQuotaBO();
        Long totalCount = deviceEntity.getTotalCount();
        Double quantityRate = 0d, performanceRate = 0.0, availability;


        //feature(2022.01.13): 计算今日生产总数， -->设备表存的是设备当年总的生产数
        //获取该设备的今日不合格数
        Map<String, String> badCountMap = feignManager.getBadProductCountByDevice(deviceEntity.getName());
        //截止昨天，该设备的生产总数
        Long lastDayProductTotal = dayReporterService.getLastDayProductTotal(deviceId);
        if(!ObjectUtils.isEmpty(lastDayProductTotal) && lastDayProductTotal < totalCount){
            //今日生产总数
            totalCount = totalCount - lastDayProductTotal;
        }

        //合格率计算： 合格数量/总数量
        deviceQuota.setQuantity(0d);
        if(!ObjectUtils.isEmpty(totalCount) && totalCount > 0){
            //今日不合格数
            Long badCount = 0l;
            String badNumber = badCountMap.get(deviceEntity.getName());
            if(!ObjectUtils.isEmpty(badNumber)){
                badCount = Long.parseLong(badNumber);
            }

            quantityRate = 1.0 * (totalCount - badCount) / totalCount;
            deviceQuota.setQuantity(quantityRate);
        }


        //性能开动率计算：
        //通过mes获取设备的节拍和报工数量的乘积
        Date start = DateUtil.getCurrentZero(new Date());
        Map<String, Double> workReportOfDay = getBeatMultiplyWorkReportOfDay(deviceEntity.getName(), start, new Date(), "day");

        //获取当前设备的节拍数与报工数量的乘积
        Double beatAndTotal = workReportOfDay.get(deviceEntity.getName());
        if(ObjectUtils.isEmpty(beatAndTotal)){
            beatAndTotal = 0.0;
        }

        //fixed(2022.02.21): mes获取透传的节拍和报工数乘积，mes改成以分钟为单位，这里需要适配一下
        beatAndTotal = beatAndTotal * 60;

        //取当前设备当天的所有运行时长(单位：秒)
        int sumRunning = deviceStatusTimeLineService.getSumRunningTimeDay(deviceEntity.getId());

        //性能开动率 = 节拍数 * 报工数量 / 有效运行时长
        if(sumRunning > 0){
            performanceRate = 1.0 * beatAndTotal / sumRunning;
        }
        deviceQuota.setPerformance(performanceRate);


        //时间开动率计算：
        //取当前设备当天的所有记录时长(单位：秒)
        int sumTime = deviceStatusTimeLineService.getSumTime(deviceEntity.getId());
        //fixed(2022.04.07): 获取实时开机时长,与历史开机时长相加    2022.04.07
        Long realOpeningTimeCurrentDay = deviceStatusTimeLineService.getRealOpeningTimeCurrentDay(deviceEntity.getId());
        sumTime = sumTime + realOpeningTimeCurrentDay.intValue();
        log.info("当前设备的实时总开机时间：{}", sumTime);

        availability = sumTime <= 0 ? 0 : (1.0 * sumRunning) / sumTime;
        deviceQuota.setAvailability(availability);


        //oee计算：
        Double oeeRate = quantityRate * performanceRate * availability;
        deviceQuota.setOee(oeeRate);


        deviceQuota.setDeviceName(deviceEntity.getName());
        deviceQuota.setSerialNumber(deviceEntity.getSerialNumber());

        return deviceQuota;
    }


    @Override
    public List<DeviceTotalInfo> getDeviceTotalInfo() {
        return deviceDao.getDeviceTotalInfo();
    }

    @Override
    public List<DeviceEntity> getAllList(){
        return deviceDao.getAllList();
    }

    @Override
    public DeviceEntity getInfo(String id){
        DeviceEntity entity = deviceDao.getInfo(id);
        return entity;
    }

    public DeviceEntity getDeviceByName(String name){
        LambdaQueryWrapper<DeviceEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DeviceEntity::getName, name);
        List<DeviceEntity> deviceEntities = deviceDao.selectList(queryWrapper);
        if(deviceEntities.size() > 0){
            return deviceEntities.get(0);
        }
        return null;
    }
}
